package 泛型;

import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Function;
/*
定义了两个泛型void函数：(无返回)
public class StaticFans {  
    //静态函数  
    public static  <T> void StaticMethod(T a){  
        Log.d("harvic","StaticMethod: "+a.toString());  
    }  
    //普通函数  
    public  <T> void OtherMethod(T a){  
        Log.d("harvic","OtherMethod: "+a.toString());  
    }  
}  
上面分别是静态泛型函数和常规泛型函数的定义方法，与以往方法的唯一不同点就是在返回值前加上<T>来表示泛型变量。其它没什么区别。
使用方法如下：
//静态方法  
StaticFans.StaticMethod("adfdsa");//使用方法一  
StaticFans.<String>StaticMethod("adfdsa");//使用方法二  

//常规方法  
StaticFans staticFans = new StaticFans();  
staticFans.OtherMethod(new Integer(123));//使用方法一  
staticFans.<Integer>OtherMethod(new Integer(123));//使用方法二 

首先，我们看静态泛型函数的使用方法：
StaticFans.StaticMethod("adfdsa");//使用方法一  
StaticFans.<String>StaticMethod("adfdsa");//使用方法二  
从结果中我们可以看到，这两种方法的结果是完全一样的，但他们还有些区别的，区别如下：
方法一:可以像普通方法一样，直接传值，任何值都可以（但必须是派生自Object类的类型，比如String,Integer等），函数会在内部根据传进去的参数来识别当前T的类别。
      但尽量不要使用这种隐式的传递方式，代码不利于阅读和维护。因为从外观根本看不出来你调用的是一个泛型函数。
方法二:与方法一不同的地方在于，在调用方法前加了一个<String>来指定传给<T>的值，如果加了这个<String>来指定参数的值的话，那StaticMethod（）函数里所有用
      到的T类型也就是强制指定了是String类型。这是我们建议使用的方式。
同样，常规泛型函数的使用也有这两种方式：
StaticFans staticFans = new StaticFans();  
staticFans.OtherMethod(new Integer(123));//使用方法一  
staticFans.<Integer>OtherMethod(new Integer(123));//使用方法二  
可以看到，与平常一样，先创建类的实例，然后调用泛型函数。
方法一:隐式传递了T的类型，与上面一样，不建议这么做。
方法二:显示将T赋值为Integer类型，这样OtherMethod（T a）传递过来的参数如果不是Integer那么编译器就会报错。
*/
import java.util.function.Predicate;


/*
上面我们的函数中，返回值都是void，但现实中不可能都是void，有时，我们需要将泛型变量返回，
方法返回泛型的一般形式：
public <T> T getObject(Class<T> cls) {
	//前<T>:声明此方法持有一个类型T,也可以理解为此方法为泛型方法。T:该方法返回类型为T
	//Class<T>：指明泛型T的具体类型。 c:用来创建泛型T代表的类的对象
	T t=cls.getDeclaredConstructor().newInstance();//创建对象
	return t;
}
*/
/*
又如下面这个函数：
public static <T> List<T> parseArray(String response,Class<T> object){  
    List<T> modelList = JSON.parseArray(response, object);  
    return modelList;  
} 
*/
//例子：
/*
class Clss1 {
    public void do1() {
        System.out.println("clss1...");
    }
}

class Clss2 {
    public void do2() {
        System.out.println("clss2...");
    }
}*/
//方式一:返回需强制转型；直接输类名作为参数。
/*
public class 方法返回泛型{
	//@SuppressWarnings("unchecked")
	public static <U extends Object> U getInstance(String clsName) throws Exception{
            Class<?> cls = Class.forName(clsName);//?表示使用泛型，T表示声明泛型，T不能出现在泛型表达式中。
            return (U)cls.getDeclaredConstructor().newInstance();//(U) 利用泛型在初始化方法里提前做了强制类型转化
	}
	public static <T> T[] getArray(Class<T> cls,int size){
		return (T[])Array.newInstance(cls,size);
	}
	public static void main(String[] args) throws Exception{
		Cls1 i1 = 方法返回泛型.getInstance("泛型.Cls1");//输入字符串类型表示的类名
		System.out.println(i1.toString());
		i1.do1();
		
		Cls2 i2 = 方法返回泛型.getInstance("泛型.Cls2");
		i2.do2();
		
		//Cls2 a = 方法返回泛型.getInstance("java.util.ArrayList");
		//System.out.println(a.toString());
		
		List<Integer> list=new ArrayList<Integer>();
		Class<?> cls = Class.forName("java.util.ArrayList");
	    Method m = cls.getDeclaredMethod("iterator",new Class[0]);
	    System.out.println(m.toString());
	    System.out.println(new Class[0]);
	    m.invoke(list,new Object[0]);
	    
	    Class clazz1 = Class.forName("java.lang.String");
	    Object array1=getArray(clazz1,10);
	    
	    Class clazz2 = Class.forName("java.lang.Integer");
	    Object array2=getArray(clazz2,10);
	}
}
*/
//方式二：不需强制转型
/*
public class 方法返回泛型{
	public  <U extends Object> U getInstance(Class<U> cls) throws Exception {
            return cls.getDeclaredConstructor().newInstance();
	}
	public static <U extends Object> U getInstance1(Class<U> cls) throws Exception{
        return cls.getDeclaredConstructor().newInstance();
}
	public static void main(String[] args) throws Exception{
		Clss1 c1 = new 泛型与反射().getInstance(Clss1.class);//U:Class1
		System.out.println(c1.toString());
		c1.do1();
		
		Clss2 c2 = 泛型与反射.getInstance1(Clss2.class);//U:Class2
		System.out.println(c2.toString());
		c2.do2();
		
		String s = getInstance1(String.class);//U:String
		Integer i = getInstance1(Integer.class);//U:Integer
		
		ArrayList l = getInstance1(ArrayList.class);//"java.util.ArrayList"
		
	}
}
*/

//定义
/*
public class 方法返回泛型{
	public static <T> T[] fun1(T...arg){  // 接收可变参数    
		return arg ;            // 返回泛型数组    
	}    
	//使用  
	public static void main(String args[]){    
		Integer i[] = fun1(1,2,3,4,5,6) ;  
		Integer[] result = fun1(i) ;
		System.out.println(Arrays.toString(i));//[1, 2, 3, 4, 5, 6]
		System.out.println(Arrays.toString(result));//[1, 2, 3, 4, 5, 6]
     
		String s[]=fun1("aa","bb","cc","dd");
		String[] result1=fun1(s);
		System.out.println(Arrays.toString(result1));//[aa, bb, cc, dd]
     
	}
}
*/

//Function函数式接口
//@FunctionalInterface
//public interface Function<T, R> {
//
//  R apply(T t);
//
//  default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
//      Objects.requireNonNull(before);
//      return (V v) -> apply(before.apply(v));
//      //B.compose(A).apply(5)
//      //compose等价于B.apply(A.apply(5))，
//  }
//
//  default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
//      Objects.requireNonNull(after);
//      return (T t) -> after.apply(apply(t));
//      //B.andThen(A).apply(5))
//      //等价于A.apply(B.apply(5))。
//  }
//
//  static <T> Function<T, T> identity() {
//      return t -> t;
//  }
//}
//其中：
//default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
//Objects.requireNonNull(before);
//return (V v) -> apply(before.apply(v));
//}
//翻译过来就是：接收一个function类型的函数作为参数.
//示例：
/*
public class 方法返回泛型{
	public static void main(String[] args) {
		System.out.println(funtest(3,i->2*i+1,j->j*j));
	}
	public static int funtest(int n,Function<Integer,Integer> func1,Function<Integer,Integer> func2) {
		//return func1.apply(func2.apply(n));
		//or:
		return func1.compose(func2).apply(n);
	}
}
*/

/*
public class 方法返回泛型 {
	public static void main(String[] args) {
		System.out.println(fun("String"));
		System.out.println(fun(10000));
	}
	public static <T> T fun(T t) {
		System.out.println(t);
		return t;
	}
//	public static <T> T seleOne(Connection conn,String sql,Class<T> clz,Object...params) {
//		
//	}
}
*/
//default Consumer<T> andThen(Consumer<? super T> after) {
//  Objects.requireNonNull(after);
//  return (T t) ‐> { accept(t); after.accept(t); }; 
//  //1:  返回值为Consumer 那么需要 ()-> 表示函数式接口
//  //2:  accept(t);为生产一个数据供应给 (T t)中的t
//  //3:  after.accept(t);为利用这个t再次生成新的函数式接口 实现类始于builder的设计模式
//}
//按照格式“ 姓名：XX。性别：XX。 ”的格式将信息打印
/*
public class 方法返回泛型 {
	//{ "迪丽热巴,女", "古力娜扎,女", "马尔扎哈,男" }
	private static void prin(Consumer<String> one,Consumer<String> two,String[] array) {
		for (String t:array) {
			one.andThen(two).accept(t);
		}
	}
	
	public static void main(String[] args) {
		String[] datas={ "迪丽热巴,女", "古力娜扎,女", "马尔扎哈,男" };
		prin(s->System.out.print(s.split("\\,")[0]),
				s->System.out.println(":"+s.split("\\,")[1]),
				datas);
		String s="abcdef";
		String b="b";
		System.out.println(s.indexOf(b));
	}
}
*/
//Predicate
//1. 必须为女生； 
//2. 姓名为4个字。
/*
public class 方法返回泛型 {
	//{ "迪丽热巴,女", "古力娜扎,女", "马尔扎哈,男" }
	private static void prin(Predicate<String> con1,Predicate<String> con2,String[] array) {
		for (String t:array) {
			if (con1.and(con2).test(t)) {
				System.out.println(t);
			}
		}
	}
	
	public static void main(String[] args) {
		String[] datas={ "迪丽热巴,女", "古力娜扎,女", "马尔扎哈,男" };
		prin(s->s.split("\\,")[0].length()==4,
				s->s.split("\\,")[1].equals("女"),
				datas);
		String s="abcdef";
		String b="b";
		System.out.println(s.indexOf(b));
	}
}*/

//使用 Function 进行函数模型的拼接，按照顺序需要执行的多个函数操作为：
//
//String str = "赵丽颖,20";
//1. 将字符串截取数字年龄部分，得到字符串；
//2. 将上一步的字符串转换成为int类型的数字；
//3. 将上一步的int数字累加100，得到结果int数字。
/*
public class 方法返回泛型 {
	private static void prin(Function<String,String> f1,Function<String,Integer> f2,Function<Integer,Integer> f3,String str) {
		System.out.println(f1.andThen(f2).andThen(f3).apply(str));//1.->2.->3.
		//or
		//System.out.println(f3.compose(f2).compose(f1).apply(str));//1.->2.->3.
	}
	public static void main(String[] args) {
		String str = "赵丽颖,20";
		//1.->2.->3.
		prin(s->s.split("\\,")[1],s->Integer.valueOf(s),s->s+100,str);
	}
}
*/

/*
public interface BinaryOperator<T> extends BiFunction<T,T,T>

public interface BiFunction<T, U, R> {
    R apply(T t, U u);
}
*/
import java.util.function.BinaryOperator;
import java.util.function.BiFunction;
public class 方法返回泛型 {
	public static void main(String[] args) {
		//BinaryOperator<T> extends BiFunction<T,T,T> 即：输入的两个参数类型与返回参数类型相同
		//此处皆为Integer
		BinaryOperator<Integer> add = (n1, n2) -> n1 + n2;//使用BiFunction<T,T,T>接口
		//apply方法用于接收参数，并返回BinaryOperator中的Integer类型
		System.out.println(add.apply(3, 4));//7
		
		BinaryOperator<String> cancat = (s1, s2) -> s1 +" 连接 "+ s2;
		System.out.println(cancat.apply("3", "4"));//3 连接 4
		
		System.out.println(addTest(3,4,(n1,n2)->n1+n2));
		System.out.println(addTest("3","4",(s1,s2)->s1+" 连接 "+s2));
	}
	//public static <T> T addTest(T n1,T n2,BinaryOperator<T> add) {
	//	return add.apply(n1, n2);
	//}
	//or
	public static <T> T addTest(T n1,T n2,BiFunction<T,T,T> add) {
		return add.apply(n1, n2);
	}
}